Polish version - English version - User manual - Download: tg-0.11.tgz

temgen - user documentation

1. Introduction

Temgen is an universal code generator, based on
template language. Temgen templates are text files consisting of control lines and data lines. Temgen rewrites data lines to output files in order defined by control lines. Variable symbols are expanded before writing output, and Function calls are replaced with the call result.

Temgen can be used for generating any text containing repeatable patterns. All generation logic is contained in templates, so Temgen can be applied to generating texts in any languages, such as C, Perl, HTML, or even natural languages.

Mechanism @embed and @emit allows to create templates generating code in several files in the same time.

2. Temgen invocation

Temgen invocation
    temgen [options] file ...    

Available options:

3. Template language

Basis Commands Built in functions

Generating text

Generating flow is following: Whole source files are parsed one after another and then interpreted in the same order. Each file is interpreted line by line, but the order can be modified with the control lines. Source file (template) consists of two kind of lines: control lines and data lines.

Control lines

Each control line starts with @ and command identifier. Command identifiers are enumerated in the table and described below. The command purpose is changing control flow (ex. @if, @switch), defining function ( @function ), interpreting code fragments in order to initialize variables ( @ ), and setting output file and emit point (the point where output text is to be placed ( @output, @embed, @emit ). Control lines can be continued in next row. Continued line should end with backslash and the next line has to start with @.

Control line continuation:
    @if ( $very_long_expression == \
    @     $another_very_long_expression )       

Data lines

Data lines contain text of the generated code. The text is expanded - encountered expressions are substituted with values. After expansion the text is inserted in embed point. The embed point defaults to end of current output file, but can be changed with the two commands: @emit and @embed. The output file can be set by @output command.

Data lines (template and output)
    @  $name = "Alaska"      
    $name is the best !    
    Alaska is the best !    

The strings can be escaped with backslash in order to prevent interpretation.

Escaping (template and output)
    @  $name = "Alaska"      
    (variable \$name)     
    (variable $name)      

Data types and expressions

There are three data types in the template language: scalars, arrays and structures. Scalars can be strings or numbers, arrays are indexed with integer numbers greater or equal 0.

Scalars, arrays and structures:
    @  $s = "BAR"
    @  $n = 2
    @  $tab[1] = "foo" 
    @  $tab[2] = "bar" 
    @  $str = [ name: "FOO", count: 4 ]
      $s   $tab[ 1 ]    $tab[ $n ]
      $str.name, $str.count
      BAR   foo    bar      
      FOO, 4             

Arrays and structures can be expanded dynamically. The iteration over all elements is supported:

Arrays and structures - iterating
    @  $tab = ["a","b","c",1000]
    @  $str = [ name: "FOO", count: 4, val: 1.20 ]
    @for ($i=0; $i<$size($tab); $i++)
       item $i: $tab[ $i ]
    @endfor
    STRUCTURE:
    @for ($i in $str)
       $i: $str.$i 
    @endfor    
    item 0: a
    item 1: b
    item 2: c
    item 3: 1000
    STRUCTURE:
    name: FOO 
    count: 4 
    val: 1.200000 

Arrays and structures may be nested.

Nested data structures:
   @ $data = [ "scalar", [a:"Alaska", b:"Bar"], \     
   @           [1,2,3,4],                       \     
   @           10 ]

Expressions

Expressions can be used in control lines and in data lines. One can use constant expressions (numbers and strings), selectors (giving an access to array or structure items), constructors (creating arrays and structures), arithmetic expressions and function calls. Any expression can be enclosed in symbols $( ); sometimes (in data lines) it must be enclosed, because only tokens starting with $ are interpreted as expressions in data lines. The addition operator ( + ) has additional meaning: it is used as string concatenation operator.

Available operators (semantics as in C):
    -          ==        ++ (postfix and prefix)  
    +          !=        -- (postfix and prefix)   
    *           =        &&
    /           <        ||
    -=          >
    +=         <=
    *=         >=
    /=          !

Expression examples:
    1    1.01   "foo"   'bar'    
    $x -= 10
    [ 1, 2, "FOO" ]
    [ name: "foo", val: 0 ]
    $fun( 10, $x )
    $var.x
    $var.$field
    $tab[ 10 ]
    $( 'Foo bar bazoola' )
    numbers and strings
    arithmetic expression 
    array constructor  
    structure constructor 
    function call    
    selector (field access)  
    selector (access by name)              
    selector (item access)         
    parenthesed expression

Each data line is expanded by substituting expression with calculated values. For function calls, value is the string returned from function with @return command. The data lines interpreted inside the function do not cause text emitting. When the function is called from control line, the rule is reversed: returned value is ignored and data lines from the function body are expanded and emitted. This sounds complicated, so you should read the example:

Function call:
    @function fun()
        inline text
    @   return "RESULT TEXT"    
    @endfunction
    called from data line: $fun()  
    @ $fun()    
    called from data line: RESULT TEXT   
        inline text

Control commands

@

The lines started with @ after which there is an expression are interpreted by calculating the expression. The evaluated value is then ignored - as in C, the side effects are the goal of such expression-instruction.

Expression instructions
    @ $fun()    
    @ $x = 1

@ break

@break command works as C language break instruction. It breaks @for loop and @switch instruction.

@break command:
    @for ( $i=0; $i<10; $i++ )  
       iteration  $i
    @  break
    @endfor
      
    @switch ( 1 )
    @  case 1:
       branch 1
    @  break   
    @  case 2:
       branch 2
    @endswitch    
   iteration  0     
   branch 1

@ embed
@ emit

The two commands @embed and @emit allow to change order of generated lines. @embed defines point in which the text will be emitted, @emit redirects output stream to emit point declared in other place. This is important that emit point can be declared in different source file before - or after - @emit command. It can emit text to different output file. The four commands: @emit, @embed, @push, @pop are probably the most robust mechanism of Temgen .

@embed and @emit accept any expression as argument, not only constant strings.

@embed 'Name' means: emit here after finding @emit 'Name'.
@emit 'Name' means: emit in point marked with @embed 'Name'.

Emit points:
    @embed "header"
    @embed "body"
    @embed "footer"   
    @emit  "body"
      BODY TEXT
    @emit  "footer"
      FOOTER TEXT
    @emit  "header"    
      HEADER TEXT
    HEADER TEXT   
    BODY TEXT
    FOOTER TEXT

@ for

The basic form of @for works similar as in C language. The loop can be broken with the @break command. The second form is used for iterating over structure fields.

Loops:
    @for ( $i=0; $i<3; $i++ )
       item  $i
    @endfor

    @  $str = [ a: "FOO", b: "BAR" ]    
    @for ( $fld in $str )
       $fld: $str.$fld 
    @endfor    
       item  0     
       item  1
       item  2
       a: FOO 
       b: BAR 

@ function

@function command starts function definition. Argument names are enumerated in function header. @return command is used to return function result. As explained before, function call effect depends on the function call place. Functions can be called in any template file, before or after function declaration. The command @local is used to declare local variables.

Function:
    @function factor( n )
    @  if ( $n == 1 )
    @     return 1
    @  else
    @     return $n * $factor( $n - 1 )   
    @  endif    
    @endfunction
   
    @for ( $i=1; $i<8; $i++ )
       $i ! = $factor($i)
    @endfor
     1 ! = 1
     2 ! = 2
     3 ! = 6
     4 ! = 24
     5 ! = 120
     6 ! = 720
     7 ! = 5040    

@ if

The conditional command @if is classic. It is presented in many examples here.

@ local

The @local command allows to declare local variable in function.

Local variable:
   @function abc(a,b)   
   @local c    
      $a $b $c
   @   $a='anew'
   @   $b='bnew'
   @   $c='cnew'
      $a $b $c
   @endfunction
   
   @ $a='a'
   @ $b='b'
   @ $c='c'

   $a $b $c
   @ $abc( $a, $b )
   $a $b $c
    a b c
        a b 
        anew bnew cnew   
    a b c

@ output

Command @output interpretation causes switching output file to file named in argument. Together with the four command: @embed, @emit, @pop and @push it constitutes command set used to control generation output. Special file name "stdout" is used to redirect text to standard output of generator.

Controlling output:
    @output "foo" 
      FOO
    @output "stdout"  
      STDOUT

@ pop
@ push

@pop and push are used to save and restore emit point. Emit point is set by commands @output (file) and @emit (line). @pop and @push are useful inside function body, allowing to restore emit point to its state before function entry.

@Push and @pop:
    @function decl( d )
    @  push
    @  output "example.h"
         $d
    @  pop
    @endfunction    
            
    @output "example.c"
        
    #include "example.h"
        
    @ $decl( "int i;" )
        
    int main()
    {
    @ $decl( "int result;" )   
          return result;    
    }
example.h:

   int i;
   int result;

example.c:

#include "example.h"   
int main()
{
      return result;    
}

@ return

The @return ends function call and returns result.

@ switch

The @switch command has syntax similar to switch instruction in C language. The difference is in @case labels. One can use any expressions as @case labels, not only constant literals, as in C. The @break is used analogous to language C.

@switch command:
    @function string( len )
    @  if ( $len == 1 )
    @     return "z"
    @  else
    @     return "z" + $string( $len-1 )   
    @  endif 
    @endfunction    
      
    @switch "zz"
    @  case $string(1) :
          1
    @     break  
    @  case $string(2) :
          2
    @     break  
    @  case $string(3) :
          3
    @     break  
    @endswitch
     2      

@ use

The @use command (known from Perl) allows to load template code from external file. The file name must be given as constant string. Loaded code is not interpreted, but the functions defined in the code are available. Temgen checks for redundant loading, skipping already loaded files.

@use command:
   @use "foo.tg"    
   @  $foo()
   FOO     

$printf()

The $printf function is used to expression formatting. It works similar to functions from printf (3) family.

$printf()
    $printf( "%-10s %d 0x%02X", "foo", 10, 10 ) 
 foo        10 0x0A  

$size()

The $size function returns size (number of fields) of compound object.

$size()
    @ $x = 1
    @ $y = [ 1, 2, 3 ]
    @ $z = [ a:"foo", b:10 ]
    
    $size($x)  $size($y)  $size($z)  $size($undef)  
  0  3  2  0   

$strlen()

The $strlen function returns length of string.

$strlen()
    @ $x = 1
    @ $y = "Foo Bar"
   
    $strlen($x)  $strlen($y)  $strlen($undef)
    0  7  0   

$substr()

The $substr function returns substring starting from given point, having given length (or up to the end - if only two arguments are used).

$substr()
    $substr( "ABCDEFGHIJK", 2, 5 )
    $substr( "ABCDEFGHIJK", 2 )
    $substr( "ABCDEFGHIJK", 2, 50 )
  CDEFG
  CDEFGHIJK   
  CDEFGHIJK

$system()

The $system function executes system command, reads the command output and returns its content.

$system()
    $system("ps")   
      PID TTY          TIME CMD
      348 pts/0    00:00:00 bash   
      713 pts/0    00:00:00 tg
      714 pts/0    00:00:00 ps

$tplfile()
$tplline()

The two functions returns current file name and line number in template.

$tplfile(), $tplline()
    \#line  $tplline()  \"$tplfile()\"     
#line  2  "sample.tg"      

4. Examples

In the sample/ directory there are some examples of temgen templates.
  1. sample/class/ - using temgen to C++ code generating
  2. sample/docex/ - examples from the documentation
  3. sample/getopt/ - classic example - command line options

5. Author, license

Marek Letowski is the author (mletowski@firma.interia.pl). All comments and suggestions are appreciated. The program is distributed with full source code, on the terms of GNU General Public License.


Polish version - English version - User manual - Download: tg-0.11.tgz